package main

import (
	"context"
	"fmt"
	"log"
	"net/http"
	_ "net/http/pprof"
	"runtime"
	"time"
)

func foo() {
	time.Sleep(100 * time.Millisecond)
}

func handleRequest(timeout time.Duration) bool {
	ctx, cancel := context.WithCancel(context.Background())
	fooChan := make(chan struct{}, 1)
	go func() {
		foo()
		fooChan <- struct{}{}
	}()

	go func() {
		time.Sleep(timeout)
		cancel()
	}()

	select {
	case <-fooChan:
		fmt.Println("foo finish")
	case <-ctx.Done():
		fmt.Println("timeout")

	}
	return true
}

func handleRequestWithTimeout(timeout time.Duration) {
	ctx, cancel := context.WithTimeout(context.Background(), timeout)
	defer cancel()
	fooChan := make(chan struct{}, 1)
	//fooChan := make(chan struct{})  //无缓冲通道，会阻塞
	WorkPool <- struct{}{}
	go func() {
		foo()
		fooChan <- struct{}{}
		<-WorkPool
	}()

	select {
	case <-fooChan:
		fmt.Println("foo finish")
	case <-ctx.Done():
		fmt.Println("timeout")
	}
}

var WorkPool = make(chan struct{}, 100)

func main() {
	//handleRequest(1 * time.Second)
	go func() {
		if err := http.ListenAndServe("0.0.0.0:8080", nil); err != nil {
			panic(err)
		}
	}()

	ticker := time.NewTicker(1 * time.Second)
	defer ticker.Stop()
	go func() {
		for {
			<-ticker.C
			log.Println("num of goroutine: ", runtime.NumGoroutine())
		}
	}()

	for {
		handleRequestWithTimeout(50 * time.Millisecond)
	}

}
